package task2;

import java.util.Arrays;
import java.util.Scanner;

/**
 * 编程实现五子棋
 */
public class Game {

    // 棋盘尺寸
    private static final int N = 16;
    // 棋盘
    private static char[][] qiPan = new char[N][N];
    // 黑方获胜条件
    private static char[] black_win = {'*', '*', '*', '*', '*'};
    // 白方获胜条件
    private static char[] white_win = {'@', '@', '@', '@', '@'};
    private static Game game = new Game();

    // 开始五子棋游戏
    public static void play(){
        // 1.绘制棋盘
        game.drawQiPan('+');
        // 2.创建两名棋手
        Player black = new Player(PlayerType.BLACK);
        Player white = new Player(PlayerType.WHITE);
        // 3.当一直没有得出输赢时，黑白方交替下棋
        while (true){
            // 3.黑方落子
            game.play(black);
            if (game.judge(Game.qiPan))
                break;
            // 4.白方落子
            game.play(white);
            if (game.judge(Game.qiPan))
                break;
        }
    }

    // 绘制空棋盘
    public static void drawQiPan(char chess, int... point) {
        // 如果输入字符是+，表示绘制空棋盘
        if (chess == '+') {
            System.out.println("初始化棋盘：");
            for (int i = 0; i < N; i++) {
                for (int j = 0; j < N; j++) {
                    if (i == 0) {
                        if (j < 10)
                            qiPan[i][j] = (char) (j + 48);
                        else
                            qiPan[i][j] = (char) (j + 87);
                    } else if (j == 0) {
                        if (i < 10)
                            qiPan[i][j] = (char) (i + 48);
                        else
                            qiPan[i][j] = (char) (i + 87);
                    } else {
                        qiPan[i][j] = chess;
                    }
                }
            }
        }
        // 如果输入字符为*，并且后面有坐标，表示黑方落子
        else if (chess == '*' && point.length == 2) {
            qiPan[point[0]][point[1]] = chess;
        }
        // 如果输入字符为@，并且后面有坐标，表示白方落子
        else if (chess == '@' && point.length == 2) {
            qiPan[point[0]][point[1]] = chess;
        }
        show(qiPan);
    }

    // 棋手出棋
    public static void play(Player player) {
        // 设置标志符，判断落子是否合法
        boolean flag = true;
        // 接受黑方棋子输入
        int[] black_point = new int[2];
        // 接受白方棋子输入
        int[] white_point = new int[2];

        if (player.getPlayerType().getName() == "黑方") {
            System.out.println("请黑方下棋,输入要落子的横、纵坐标(范围为1～15)，以空格分开：");
            // 黑方的棋子为*
            while (flag) {
                Scanner scanner = new Scanner(System.in);
                black_point[0] = scanner.nextInt();
                black_point[1] = scanner.nextInt();
                /*if ((black_point[0] > 0 && black_point[0] < 10) && (black_point[1] > 0 && black_point[1] < 10) && qiPan[black_point[0]][black_point[1]] == '+'){
                    drawQiPan('*',black_point[0],black_point[1]);
                }*/
                if ((black_point[0] > 0 && black_point[0] < 16) && (black_point[1] > 0 && black_point[1] < 16)) {
                    if (qiPan[black_point[0]][black_point[1]] == '+')
                        flag = false;
                    else
                        System.out.println("该位置已落子，请重新选择位置！");
                } else
                    System.out.println("输入越界，请重新输入！");
            }
            drawQiPan('*', black_point[0], black_point[1]);
        } else {
            flag = true;
            System.out.println("请白方下棋,输入要落子的横、纵坐标(范围为1～15)，以空格分开：");
            while(flag){
                // 白方的棋子为@
                Scanner scanner = new Scanner(System.in);
                white_point[0] = scanner.nextInt();
                white_point[1] = scanner.nextInt();
                if (white_point[0] > 0 && white_point[0] < 16 && white_point[1] > 0 && white_point[1] < 16) {
                    if (qiPan[white_point[0]][white_point[1]] == '+')
                        flag = false;
                    else
                        System.out.println("该位置已落子，请重新选择位置！");
                }else
                    System.out.println("输入越界，请重新输入！");
            }
            drawQiPan('@', white_point[0], white_point[1]);
        }
    }

    // 判断连续的棋子个数
    public static boolean judge(char[][] qiPan) {
        // 临时数组，保存连续棋子
        char[] temp = new char[5];
        // 是否获胜标志
        boolean flag = false;

        // 在行中判断是否有5个连续的棋子
        for (int i = 1; i < N; i++) {
            for (int j = 1; j <= N - 5; j++) {
                // 将第i行的j到j+5之间的棋子拿出来判断
                temp = Arrays.copyOfRange(qiPan[i], j, j + 5);
                // 黑方获胜
                if (Arrays.equals(temp, black_win)) {
                    System.out.println("黑方获胜！");
                    return true;
                }
                // 白方获胜
                else if (Arrays.equals(temp, white_win)) {
                    System.out.println("白方获胜！");
                    return true;
                }
            }
        }
        temp = clear(temp);

        // 在列中判断是否有5个连续的棋子
        for (int i = 1; i < N; i++) {
            for (int j = 1; j <= N - 5; j++) {
                // 将第j列的i到i+5之间的棋子拿出来判断
                for (int k = 0; k < 5; k++)
                    temp[k] = qiPan[j + k][i];
                // 黑方获胜
                if (Arrays.equals(temp, black_win)) {
                    System.out.println("黑方获胜！");
                    return true;
                }
                // 白方获胜
                else if (Arrays.equals(temp, white_win)) {
                    System.out.println("白方获胜！");
                    return true;
                }
                temp = clear(temp);
            }
        }
        temp = clear(temp);

        // 在左上角到右下角判断是否有5个连续的棋子
        for (int n = 4; n < N - 1; n++) {
            for (int i = 1, j = i + n; (i <= n + 1) && (j >= 1); i++, j--) {
                // 将斜着连续的5个棋子拿出来判断
                for (int k = 0; k < 5; k++)
                    if (i + k <= n + 1)
                        temp[k] = qiPan[i + k][j - k];
                // 黑方获胜
                if (Arrays.equals(temp, black_win)) {
                    System.out.println("黑方获胜！");
                    return true;
                }
                // 白方获胜
                else if (Arrays.equals(temp, white_win)) {
                    System.out.println("白方获胜！");
                    return true;
                }
                temp = clear(temp);
            }
        }
        temp = clear(temp);

        for (int n = 4; n < N - 1; n++) {
            for (int j = 15, i = j - n; (i < N); i++, j--) {
                // 将斜着连续的5个棋子拿出来判断
                for (int k = 0; k < 5; k++)
                    if (i + k <= 15)
                        temp[k] = qiPan[i + k][j - k];
                // 黑方获胜
                if (Arrays.equals(temp, black_win)) {
                    System.out.println("黑方获胜！");
                    return true;
                }
                // 白方获胜
                else if (Arrays.equals(temp, white_win)) {
                    System.out.println("白方获胜！");
                    return true;
                }
                temp = clear(temp);
            }
        }
        temp = clear(temp);

        // 在右上角到左下角判断是否有5个连续的棋子
        for (int n = 10; n >= 0; n--) {
            for (int i = 1, j = i + n; (i <= N - 1 - n); i++) {
                // 将斜着连续的5个棋子拿出来判断
                for (int k = 0; k < 5; k++)
                    if (i + k <= N - 1 - n)
                        temp[k] = qiPan[i + k][j + k];
                // 黑方获胜
                if (Arrays.equals(temp, black_win)) {
                    System.out.println("黑方获胜！");
                    return true;
                }
                // 白方获胜
                else if (Arrays.equals(temp, white_win)) {
                    System.out.println("白方获胜！");
                    return true;
                }
                temp = clear(temp);
            }
        }
        temp = clear(temp);

        for (int n = 10; n >= 0; n--) {
            for (int i = 1, j = i + n; (i <= N - 1 - n); i++, j++) {
                // 将斜着连续的5个棋子拿出来判断
                for (int k = 0; k < 5; k++)
                    if (i + k <= N - 1 - n)
                        temp[k] = qiPan[j + k][i + k];
                // 黑方获胜
                if (Arrays.equals(temp, black_win)) {
                    System.out.println("黑方获胜！");
                    return true;
                }
                // 白方获胜
                else if (Arrays.equals(temp, white_win)) {
                    System.out.println("白方获胜！");
                    return true;
                }
                temp = clear(temp);
            }
        }
        return false;
    }

    // 显示棋盘
    public static void show(char[][] qiPan) {
        for (int i = 0; i < qiPan.length; i++) {
            for (int j = 0; j < qiPan[i].length; j++) {
                System.out.print(qiPan[i][j] + "\t");
            }
            System.out.println();
        }
    }

    // 数组清空
    public static char[] clear(char[] array) {
        for (int i = 0; i < array.length; i++)
            array[i] = '0';
        return array;
    }
}
